package com.canto.common.aspect;

import com.canto.common.constant.Constants;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 日志跟踪器
 * 用途：利用spring的aop打印方法调用的开始时间和结束时间，以及耗时。
 */
@Aspect     //标注增强处理类（切面类）
@Component  //交由Spring容器管理
@Order(1)   //设置优先级，值越低优先级越高
public class LogTracer {

    private Logger logger = LogManager.getRootLogger();

    /**
     * 定义一个切入点.
     * <p>
     * ~ 第一个 * 代表任意修饰符及任意返回值.
     * ~ 第二个 * 任意包名
     * ~ 第三个 * 代表任意方法.
     * ~ 第四个 * 定义在web包或者子包
     * ~ 第五个 * 任意方法
     * ~ .. 匹配任意数量的参数.
     */
    @Pointcut("@within(org.springframework.web.bind.annotation.RequestMapping) || @within(org.apache.ibatis.annotations.Mapper)")
    public void invokeLog() {
    }

    @Around("invokeLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        //开始时间
        long startTime = System.currentTimeMillis();
        //打印开始时间
        logger.info("{} {} {}", Constants.UTIL_TRACER_INVOKE_METHOD_BEGIN, proceedingJoinPoint.toString(), startTime);
        //打印传入数据
//        logger.info("{} {} {}", Constants.UTIL_TRACER_INVOKE_METHOD_ARGS, proceedingJoinPoint.toString(), JsonUtil.toArrayObj(proceedingJoinPoint.getArgs()));

        //pjp.proceed()方法个人理解为是一个对业务方法的模拟，可是在这个方法前后插入想做的事情。
        Object result = proceedingJoinPoint.proceed();

        //结束时间
        long endTime = System.currentTimeMillis();
        //打印结束时间
        logger.info("{} {} {} {} {}{}", Constants.UTIL_TRACER_INVOKE_METHOD_END, proceedingJoinPoint.toString(), endTime, Constants.UTIL_TRACER_INVOKE_METHOD_COST, (endTime - startTime), "ms");

        return result;
    }

}
